package yang.simpleMain.MyLock;
import java.util.ArrayList;
import java.util.List;

public class FairLock {

	private boolean isLocked = false;

	private Thread lockingThread = null;

	private List<QueueObject> waitingThreads = new ArrayList<QueueObject>();

	public void lock() throws InterruptedException {

		QueueObject queueObject = new QueueObject();

		boolean isLockedForThisThread = true;

		synchronized (this) {

			waitingThreads.add(queueObject);

		}

		while (isLockedForThisThread) {

			synchronized (this) {
				// 当且仅当没有锁定且第一个等待列表为自己时获得锁
				isLockedForThisThread = isLocked || waitingThreads.get(0) != queueObject;

				if (!isLockedForThisThread) {

					isLocked = true;

					waitingThreads.remove(queueObject);

					lockingThread = Thread.currentThread();

					return;

				}

			}

			try {

				queueObject.doWait();

			} catch (InterruptedException e) {

				synchronized (this) {
					waitingThreads.remove(queueObject);
				}

				throw e;

			}

		}

	}

	public synchronized void unlock() {

		if (this.lockingThread != Thread.currentThread()) {

			throw new IllegalMonitorStateException(

					"Calling thread has not locked this lock");

		}

		isLocked = false;

		lockingThread = null;

		if (waitingThreads.size() > 0) {

			waitingThreads.get(0).doNotify();

		}

	}

}
